﻿using ICSharpCode.TextEditor;
using Koala.Pro.CodeGenerator.UI.Common;
using Koala.Pro.CodeGenerator.UI.DatabaseModel.Schema;
using System.Data;
using System.Text;
using System.Text.RegularExpressions;
using WeifenLuo.WinFormsUI.Docking;

namespace Koala.Pro.CodeGenerator.UI
{
    public partial class FrmQueryAnalyzer : DockContent
    {
        private DataSet dataSet;

        private string[] arrQuery;

        private static int buttonIndex;

        public FrmQueryAnalyzer()
        {
            InitializeComponent();

            BindDatabase();
            SetEditorSetting();
        }

        private void BindDatabase()
        {
            cmbDatabase.Items.Clear();
            foreach (DatabaseInfo value in Program.global.DbInstance.DatabaseList.Values)
            {
                cmbDatabase.Items.Add(value.Name.Name.ToString());
            }
            if (cmbDatabase.Items.Count <= 0)
            {
                return;
            }
            string selectedDatabaseName = Program.global.MainView.ToolWin.GetSelectedDatabaseName();
            if (selectedDatabaseName != null)
            {
                int selectedIndex = cmbDatabase.FindStringExact(selectedDatabaseName);
                cmbDatabase.SelectedIndex = selectedIndex;
            }
            string tableName = Program.global.MainView.ToolWin.GetSelectedTableName();
            if (!string.IsNullOrEmpty(tableName))
            {
                string assemblyTypeShortName = Program.global.AssemblyTypeShortName;
                var sql = $"SELECT * FROM {tableName};";
                if (assemblyTypeShortName.Equals("sqlserver", StringComparison.OrdinalIgnoreCase))
                {
                    TableInfo tableInfo = Program.global.DbInstance.DatabaseList[selectedDatabaseName].TableList[tableName];
                    if (tableInfo.Scheme.Length > 0)
                    {
                        tableName = $"[{tableInfo.Scheme}].[{tableName}]";
                        sql = $"Select TOP 100 * from {tableName};";
                    }
                    else
                    {
                        sql = $"Select TOP 100 * from [{tableName}];";
                    }
                }
                else if (assemblyTypeShortName.Equals("oracle", StringComparison.OrdinalIgnoreCase))
                {
                    tableName = string.Format("{0}.\"{1}\"", selectedDatabaseName, tableName);
                    sql = $"SELECT * FROM {tableName} FETCH FIRST 100 ROWS ONLY;";
                }
                else if (assemblyTypeShortName.Equals("sqlite", StringComparison.OrdinalIgnoreCase))
                {
                    sql = $"SELECT * FROM {tableName} LIMIT 100;";
                }
                
                try
                {
                    txtCodeEditor.Text = sql;
                    ExecuteQuery();
                }
                catch (Exception ex)
                {
                    MessageUtil.ShowError(ex.Message);
                }
            }
        }

        public void RenderGrid(DataTable dt)
        {
            if (buttonIndex == 0)
            {
                dgResult.DataSource = dt;
                buttonIndex++;
                return;
            }
            tabResult.Controls.Add(new TabPage("结果" + buttonIndex));
            tabResult.TabPages[tabResult.TabPages.Count - 1].Name = "tabPages" + buttonIndex;
            CreateGridInTabControl(dt, "dgResult" + buttonIndex);
            buttonIndex++;
        }

        public void CreateGridInTabControl(DataTable dt, string gridName)
        {
            DataGridView dataGridView = new DataGridView();
            dataGridView.Name = gridName;
            dataGridView.DataSource = dt;
            dataGridView.Top = dgResult.Top;
            dataGridView.Left = dgResult.Left;
            dataGridView.Anchor = dgResult.Anchor;
            dataGridView.Dock = dgResult.Dock;
            dataGridView.Width = dgResult.Width;
            dataGridView.Height = dgResult.Height;
            tabResult.TabPages[tabResult.TabPages.Count - 1].Controls.Add(dataGridView);
        }

        private void SetEditorSetting()
        {
            txtCodeEditor.ShowEOLMarkers = false;
            txtCodeEditor.ShowInvalidLines = false;
            txtCodeEditor.ShowSpaces = false;
            txtCodeEditor.ShowTabs = false;
            txtCodeEditor.Encoding = Encoding.Default;
            txtCodeEditor.SetHighlighting(FormatCodeHelper.TSQL);

            txtCodeEditor.ActiveTextAreaControl.TextArea.KeyUp -= TextArea_KeyUp;
            txtCodeEditor.ActiveTextAreaControl.TextArea.KeyUp += TextArea_KeyUp;

            txtCodeEditor.ActiveTextAreaControl.TextArea.ToolTipRequest -= TextArea_ToolTipRequest;
            txtCodeEditor.ActiveTextAreaControl.TextArea.ToolTipRequest += TextArea_ToolTipRequest;
        }

        private void TextArea_ToolTipRequest(object sender, ToolTipRequestEventArgs e)
        {
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.Append("输入SQL语句后，请按F5快捷键或者顶部执行按钮执行Sql语句；\r\n多条语句请使用换行分开.");
            stringBuilder.Append("\r\nuse pubs \r\n");
            stringBuilder.Append("select * from authors \r\n");
            stringBuilder.Append("select * from titles \r\n");
            e.ShowToolTip(stringBuilder.ToString());
        }

        private void TextArea_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.F5)
            {
                ExecuteQuery();
            }
        }

        public void DisposeTabPages()
        {
            foreach (TabPage tabPage in tabResult.TabPages)
            {
                if (tabPage.Name != "tabPage0")
                {
                    tabResult.TabPages.Remove(tabPage);
                }
            }
        }

        private void ResetButtonIndex()
        {
            buttonIndex = 0;
        }

        public void ExecuteQuery()
        {
            statusLabel.Text = "执行中...";
            DisposeTabPages();
            ResetButtonIndex();
            if (dataSet != null)
            {
                dataSet.Tables.Clear();
                dataSet = new DataSet();
                arrQuery = null;
            }
            
            var queryText = txtCodeEditor.Text;
            if (txtCodeEditor.SelectedText.Trim() != string.Empty)
            {
                queryText = txtCodeEditor.SelectedText.Trim();
            }
            AddToArray(queryText);

            try
            {
                string[] array = arrQuery;
                foreach (string query in array)
                {
                    ExecuteQuery(cmbDatabase.Text, query);
                }
                foreach (DataTable table in dataSet.Tables)
                {
                    RenderGrid(table);
                }
                statusLabel.Text = "已成功执行。";
            }
            catch (Exception ex)
            {
                //MessageUtil.ShowError(ex.Message);
                statusLabel.Text = $"执行出错。{ex.Message}";
            }
        }

        private void ExecuteQuery(string database, string query)
        {
            if (dataSet == null)
            {
                dataSet = new DataSet("Result");
            }
            if (query.Trim() != string.Empty)
            {
                dataSet = Program.global.DbInstance.DatabaseList[database].ExecuteSql(query);
            }
        }

        private void AddToArray(string QueryText)
        {
            Regex regex = new Regex("\\bgo\\b", RegexOptions.IgnoreCase);
            arrQuery = regex.Split(QueryText);
        }

        private void btnExecute_Click(object sender, EventArgs e)
        {
            ExecuteQuery();
        }

        private void txtCodeEditor_DragEnter(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.Text))
            {
                e.Effect = DragDropEffects.Copy;
            }
            else
            {
                e.Effect = DragDropEffects.None;
            }
        }

        private void menu_ExecuteSql_Click(object sender, EventArgs e)
        {
            ExecuteQuery();
        }

        private void QueryAnalyzer_Activated(object sender, EventArgs e)
        {
            //BindDatabase();
            //SetEditorSetting();
        }
    }
}
